#pragma once

#include <compl/candy.h>
/* llsc的汇编实现 */
typedef word_t         llword_t;
typedef struct
{
	union{
		llword_t val;
		word_t rval;
	};
	llword_t *ptr;
} __attribute__((aligned(sizeof(llword_t)))) llsc_t;


static inline word_t __ld_link_acq(llword_t *ptr)
{
	word_t val;
	asm volatile("	ldrex	%0, [%1]\n"
			: "=&r"(val)
			: "r"(ptr)
			: "memory");
	return val;
}
static inline word_t __ld_link(llword_t *ptr)
{
	word_t val;
	asm volatile("	ldrex	%0, [%1]\n"
				 : "=&r"(val) 
				 : "r"(ptr)
				 : "memory");
	return val;
}
static inline bool_t __st_cond(llword_t *ptr, word_t new_val)
{
	word_t val;
	bool_t tmp;
	asm volatile("	strex	%0, %1, [%2]\n"
			: "=&r"(tmp)
			: "r"(new_val), "r"(ptr)
			: "memory");
	return tmp;
}
static inline word_t __st_cond(llword_t *ptr, word_t new_val)
{
	word_t val;
	bool_t tmp;
	asm volatile("	strex	%0, %1, [%2]\n"
			: "=&r"(tmp)
			: "r"(new_val), "r"(ptr)
			: "memory");
	return tmp;
}
//接口
//接口
static inline word_t ld_link(llsc_t *x, llword_t *ptr)
{
	word_t val;
	x->ptr = ptr;

	x->val = __ld_link(ptr);
	return x->val;
}

static inline word_t ld_link_acq(llsc_t *x, llword_t *ptr)
{
	x->ptr = ptr;
	x->val = __ld_link_acq(ptr);

	return x->val;
}

static inline bool_t st_cond_rel(llsc_t *x, word_t new_val)
{
	// int result;
	// // cmb();
	// asm volatile( //"	stlxr	%w0, %2, %1\n"
	// 	"	stlxr	%w0, %2, %1\n"
	// 	: "=&r"(result), "+Q"(*(x->ptr))
	// 	: "r"(new_val)
	// 	: "memory");
	
	bool_t res = __st_cond_rel(x->ptr, new_val);
	/* 等于0是成功，不等于0失败 */
	if (res){
		/* 失败了重新读取 */
		x->val = __ld_link_acq(x->ptr);
	}
	return !res;
}

static inline bool_t st_cond(llsc_t *x, word_t new_val)
{
	// int result;
	// // cmb();
	// asm volatile( //"	stlxr	%w0, %2, %1\n"
	// 	"	stxr	%w0, %2, %1\n"
	// 	: "=&r"(result), "+Q"(*(x->ptr))
	// 	: "r"(new_val)
	// 	: "memory");
	// //: "cl"	  );
	// // cmb();
	bool_t res = __st_cond(x->ptr, new_val);
	/* 等于0是成功，不等于0失败 */
	if (res){
		/* 失败了重新读取 */
		x->val = __ld_link(x->ptr);
	}
	return !res;
}

// static inline bool_t st_cond(llsc_t *x, word_t new_val)
// {
//     llword_t new_cntval = new_dword(new_val, x->cnt + 1);
//     llword_t old_val = x->val;
//     x->val = __sync_val_compare_and_swap(x->ptr, old_val, new_cntval);
//     return (old_val == x->val);
// }

// #define ld_link_acq(x, ptr)         ld_link(x, ptr)
// #define st_cond_rel(x, new_val)     st_cond(x, new_val)

